#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/string.h>

#include "./led.h"

#define NAME "XYTLEDDEV"
#define MAJOR 200 //主设备号

static void __iomem *IMX6U_CCM_CCR1;
static void __iomem *SW_MUX;
static void __iomem *SW_PAD;
static void __iomem *GPIO1_DR;
static void __iomem *GPID1_GDIR;
#define LED_ON 0
#define LED_OFF 1
static void GPIO_Init(void)
{
    int val =0;
    IMX6U_CCM_CCR1 = ioremap(CCM_CCGR1_BASE, 4);
    SW_MUX = ioremap(SW_MUX_GPIO1_IO04_BASE, 4);
    SW_PAD = ioremap(SW_PAD_GPIO1_IO04_BASE, 4);
    GPIO1_DR = ioremap(GPIO1_DR_BASE, 4);
    GPID1_GDIR = ioremap(GPIO1_GDIR_BASE, 4);
    
    writel(0xffffffff, IMX6U_CCM_CCR1);
    writel(5, SW_MUX);
    writel(0x10B0, SW_PAD);

    val = readl(GPID1_GDIR);
    val |= 1 << 4;
    writel(val, GPID1_GDIR);

    val = readl(GPIO1_DR);
    val &= ~(1 << 4);
    writel(val, GPIO1_DR);
}

void LED_Staus(int staus)
{
    int val = 0;
    if (staus == LED_ON)
    {
        val = readl(GPIO1_DR);
        val &= ~(1 << 4);
        writel(val, GPIO1_DR);
        printk("LEDON\n");
    }
    else
    {
        val = readl(GPIO1_DR);
        val |= (1 << 4);
        writel(val, GPIO1_DR);
        printk("LEDOFF\n");
    }
}

static int LED_open(struct inode *inode, struct file *fs)
{
    return 0;
}

static int LED_release(struct inode *inode, struct file *fs)
{
    return 0;
}
static ssize_t LED_read(struct file *fs, char __user *buff, size_t count, loff_t *loff)
{

    return count;
}
static ssize_t LED_write(struct file *fs, const char __user *buff, size_t count, loff_t *opps)
{
    u8 ret =0;
    char Tbuff[100] ={"      "};
    ret = copy_from_user(Tbuff,buff,count);
    if(ret < 0)
    {
        printk("write erro\n");
        return -EIO;
    }
    else 
    {
        printk("Tbuff = %s\n",Tbuff);
        if(Tbuff[0] == '0')
        {
            LED_Staus(LED_ON);
        }
        else 
        {
            LED_Staus(LED_OFF);
        }
        return count;
    }   

}

static const struct file_operations LedFs =
    {
        .owner = THIS_MODULE,
        .open = LED_open,
        .read = LED_read,
        .write = LED_write,
        .release = LED_release,
};

static int __init LED_init(void)
{
    int ret = 0;
    printk("LED init \n");
    //1.初始化LED
    GPIO_Init();

    ret = register_chrdev(MAJOR, NAME, &LedFs);
    if (ret < 0)
    {
        printk("register_chrdev error \n");
        return -EIO;
    }
    return 0;
}
static void __exit LED_exit(void)
{
    int val = 0;
    printk("LED exit \n");
    unregister_chrdev(MAJOR, NAME);

    val = readl(GPIO1_DR);
    val |= (1 << 4);
    writel(val, GPIO1_DR);

    iounmap(IMX6U_CCM_CCR1);
    iounmap(SW_MUX);
    iounmap(SW_PAD);
    iounmap(GPIO1_DR);
    iounmap(GPID1_GDIR);
    printk("unregister_chrdev LEDDEV\n");
}

module_init(LED_init);
module_exit(LED_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("xyt");


